package com.liyong.pullorder.channels.autoconfigure;

import com.liyong.pullorder.channels.auth.ApiKeyAuthStrategy;
import com.liyong.pullorder.channels.auth.AuthStrategy;
import com.liyong.pullorder.channels.auth.OAuth2AuthStrategy;
import com.liyong.pullorder.channels.core.ChannelsPullService;
import com.liyong.pullorder.channels.http.HttpClientProvider;
import com.liyong.pullorder.channels.parse.JsonParserStrategy;
import com.liyong.pullorder.channels.parse.ParserStrategy;
import com.liyong.pullorder.channels.parse.XmlParserStrategy;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
import org.springframework.retry.annotation.EnableRetry;

import java.util.Arrays;
import java.util.List;

@Configuration
@ConditionalOnClass(ChannelsPullService.class)
@EnableConfigurationProperties(ChannelsPullProperties.class)
@EnableRetry
@ConditionalOnProperty(prefix = "channels-pull-sdk", name = "enabled", havingValue = "true", matchIfMissing = true)
/**
 * 渠道拉单自动配置。
 *
 * 目标与职责：
 * - 提供 HTTP 客户端与 RestTemplate（带连接池与 UTF-8 转换器）。
 * - 装配认证策略与数据解析策略，支持多渠道（JSON/XML）拉单。
 * - 暴露核心服务 ChannelsPullService，并启用 Spring Retry 保证健壮性。
 *
 * 使用方式：
 * - 在应用配置 `channels-pull-sdk.enabled=true` 即可启用；其余参数由 `ChannelsPullProperties` 提供。
 */
public class ChannelsPullAutoConfiguration {

    @Bean
    @ConditionalOnMissingBean
    public HttpClientProvider httpClientProvider(ChannelsPullProperties properties) {
        return new HttpClientProvider(properties);
    }

    /**
     * 拉单专用 RestTemplate。
     *
     * 说明：
     * - 复用统一的 `HttpClientProvider`，保证连接池与超时参数一致。
     * - 提前插入 UTF-8 `StringHttpMessageConverter`，避免中文等字符异常。
     */
    @Bean(name = "pullOrderRestTemplate")
    @ConditionalOnMissingBean(name = "pullOrderRestTemplate")
    public RestTemplate pullOrderRestTemplate(HttpClientProvider provider) {
        return provider.restTemplate();
    }

    @Bean
    @ConditionalOnMissingBean
    public List<AuthStrategy> authStrategies() {
        return Arrays.asList(new OAuth2AuthStrategy(), new ApiKeyAuthStrategy());
    }

    @Bean
    @ConditionalOnMissingBean
    public List<ParserStrategy> parserStrategies() {
        return Arrays.asList(new JsonParserStrategy(), new XmlParserStrategy());
    }

    /**
     * 核心拉单服务。
     *
     * 职责：
     * - 整合配置、HTTP 客户端、认证策略与解析策略，面向应用提供统一的拉单入口。
     * - 内部支持重试（由 `@EnableRetry` 生效），对临时性网络波动更友好。
     */
    @Bean
    @ConditionalOnMissingBean
    public ChannelsPullService channelsPullService(ChannelsPullProperties properties,
                                                   RestTemplate pullOrderRestTemplate,
                                                   List<AuthStrategy> authStrategies,
                                                   List<ParserStrategy> parserStrategies) {
        return new ChannelsPullService(properties, pullOrderRestTemplate, authStrategies, parserStrategies);
    }
}